#include "NCManager.h"
#include "CanonicalConv.h"
#include "Domain.h"
#include <pthread.h>
#include <iostream>
#include <map>
#include "md5/md5.h"
#include <string>
#include <queue>
#include <fstream>

using namespace std;
NCManager* NCManager::mainShip;
int NCManager::visitedSites;
int NCManager::fetchedRobots;

NCManager::NCManager()
{
}

void NCManager::init()
{
	pthread_mutex_init(&domainsMutex, NULL);
	pthread_mutex_init(&queueMutex, NULL);
	pthread_mutex_init(&pageCounterMutex, NULL);
	pthread_mutex_init(&robotsCounterMutex, NULL);
	pthread_mutex_init(&donwloadedSitesMutex, NULL);
	NCManager::mainShip = this;
	NCManager::visitedSites = 0;
	NCManager::fetchedRobots = 0;
}
NCManager::~NCManager()
{
}

bool NCManager::hasDomain(string domainStr)
{
	return domains.find(domainStr)!=domains.end();
}
void NCManager::addDomain(Domain* domain)
{
	domains[domain->getDomain()] = domain;
}

void NCManager::addToVisitQueue(string url)
{
	
	//
	// Trava mutex do Dominio
	// Tenta pegar dominio, se tem continua em 1, senao vai pra 2
	// 1: Verifica se  existe site, se sim, BREAK;
	//    Senao, vai pra 2
	// 2:
	//
	
	if(isDownloaded(url))
		return;


	if(url.size() < 300)
	{
	int level=-2;  // Accounting for the  2 '/' on http://
	for(int i=0;i<=url.size();i++)
		if(url[i]=='/')
			level++;
	//cout << "Adicionei o site: " << url << endl;
	if(level == 0){
		if(P1Queue.size() < 700000)
			P1Queue.push(url);}
	else if ( level == 1){
		if(P2Queue.size() < 250000)
			P2Queue.push(url);}
	else if ( level == 2){
		if(P3Queue.size() < 100000)
			P3Queue.push(url);}
	else 
		if(P4Queue.size() < 70000)
			P4Queue.push(url);
	}
}

string NCManager::popUrlToVisit()
{
	try {
	
	int entropy = rand()%10;
	if(entropy < 5)
	{
		if(P1Queue.size() > 0)
		{
		string url = P1Queue.front();
		P1Queue.pop() ;
		return url;
		}
		else
			entropy = 5; 
	}
	if( entropy < 7)
	{
		if(P2Queue.size() > 0)
		{
			string url = P2Queue.front();
			P2Queue.pop();
			return url;
		}
		else
			entropy = 7;
	}
	if ( entropy < 8)
	{
		if(P3Queue.size() > 0)
		{
			string url = P3Queue.front();
			P3Queue.pop();
			return url;
		}
	}
		if(P4Queue.size() > 0)
		{
			string url = P4Queue.front();
			P4Queue.pop();
			return url;
		}
		
		return "?";
	}
	catch(...){}
}

Domain* NCManager::getDomain(string domainStr)
{
	return domains[domainStr];
}

queue<string>* NCManager::getVisitQueue1()
{
	return &P1Queue;
}

queue<string>* NCManager::getVisitQueue2()
{
	return &P2Queue;
}

queue<string>* NCManager::getVisitQueue3()
{
	return &P3Queue;
}

queue<string>* NCManager::getVisitQueue4()
{
	return &P4Queue;
}

bool NCManager::isDownloaded(string urlSite)
{	
	char* url = const_cast<char*>(urlSite.c_str());
	string urlMD5 = MD5String(url);	
	return downloadedSites.find(urlMD5)!=downloadedSites.end();
}

void NCManager::addToDownloadedSet(string site)
{
	char* url = const_cast<char*>(site.c_str());
	string urlMD5 = MD5String(url);
	downloadedSites.insert(urlMD5);
}

void NCManager::addToDownloadSetMD5(string site)
{
	downloadedSites.insert(site);
}
